/*
 * @# Memcached.java 2011-12-1 下午03:51:27
 * 
 * Copyright (C) 2010 - 2011 广州羿安信息科技有限公司
 * Guangzhou ianswer information technology co. ltd.
 * 
 * All rights reserved!
 */
package com.ianswer.experiments.memcached;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;

import org.apache.log4j.Logger;

import net.spy.memcached.MemcachedClient;

/**
 * @author lunx
 */
public class Memcached {

	private static MemcachedClient mc = null;

	private static final String KEY = "person";

	private static final int EXP = 30;//单位S

	private static final int TIMEOUT = 1000;//单位ms 默认为1s

	private static Logger log = Logger.getLogger(Memcached.class);

	/*
	 * 还需要批量存取方法。。。。。
	 */

	/**
	 * 获取Memcached Client连接
	 * @return
	 * @throws IOException
	 */
	public static synchronized MemcachedClient getMc() throws IOException {
		/**
		 * BinaryConnectionFactory，DefaultConnectionFactory
		 * 可以指定hash算法，队列长度(16384)，缓冲大小(16384)
		 * 
		 */
		if (mc != null) {
			return mc;
		}
		//BinaryConnectionFactory bcf = new BinaryConnectionFactory();
		//DefaultConnectionFactory dcf = new DefaultConnectionFactory();
		List<InetSocketAddress> list = new ArrayList<InetSocketAddress>();
		list.add(new InetSocketAddress("192.168.1.105", 11211));
		list.add(new InetSocketAddress("192.168.1.105", 11212));
		//MemcachedClient mc = new MemcachedClient(bcf, list);
		//MemcachedClient mc = new MemcachedClient(dcf, list);
		MemcachedClient mc = new MemcachedClient(list);
		return mc;
	}

	/**
	 * 保存对象到Memcached
	 * @param p
	 */
	public void add(Object obj) {
		try {
			mc = getMc();
			byte[] bytes = SerializerFactory.getSerializeClazz(SeriType.KRYO).serializer(obj);
			log.debug("before compress:" + bytes.length);
			byte[] gzipBytes = GzipUtil.gzip(bytes);
			log.debug("after compress:" + gzipBytes.length);
			Future<Boolean> future = mc.add(KEY, EXP, gzipBytes);
			try {
				Boolean flag = future.get(TIMEOUT, TimeUnit.MILLISECONDS);
				if (flag) {
					log.debug("add success..");
				} else {
					log.debug("already exists or timeout...");
				}
				shutdown();
			} catch (Exception e) {
				log.error(e.getMessage(), e);
				future.cancel(true);
			}
		} catch (IOException e) {
			log.error(e.getMessage(), e);
		}
	}

	/**
	 * 从Memcached获取指定key对象
	 * @param <T>
	 * @param clazz
	 * @return
	 */
	public <T> T get(String key, Class<T> clazz) {
		try {
			mc = getMc();
			//byte[] bytes = (byte[]) mc.get(key);//default timeout 1000
			Future<Object> future = mc.asyncGet(key);
			byte[] bytes = null;
			try {
				bytes = (byte[]) future.get(TIMEOUT, TimeUnit.MILLISECONDS);
			} catch (Exception e) {
				log.error(e.getMessage(), e);
				future.cancel(true);
			}
			log.debug("before uncompress:" + bytes.length);
			byte[] gzipBytes = GzipUtil.unGzip(bytes);
			log.debug("after uncompress:" + gzipBytes.length);
			shutdown();
			return SerializerFactory.getSerializeClazz(SeriType.KRYO).unSerializer(gzipBytes, clazz);
		} catch (IOException e) {
			log.error(e.getMessage(), e);
			return null;
		}
	}

	/**
	 * 关闭连接
	 */
	private static void shutdown() {
		log.debug("shutdown before isAlive:" + mc.isAlive());
		if (mc != null && mc.isAlive()) {
			mc.shutdown();
			mc = null;
		}
		log.debug("shutdown end...");
	}

	public static void main(String args[]) {
		System.out.println("begin:" + new Date().getTime());
		Person p1 = new Person();
		p1.setName("xulun");
		p1.setSex("M");
		p1.setAge(22L);
		Memcached mem = new Memcached();
		mem.add(p1);
		Person p = mem.get(KEY, Person.class);
		System.out.println("main out:" + p.toString());
		System.out.println("after:" + new Date().getTime());
	}
}
